package com.tcs.validation.task;

import java.util.List;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.tcs.cache.ICommonCacheTemplate;
import com.tcs.cache.redis.RedisCacheTemplate;
import com.tcs.check.net.INetChecked;
import com.tcs.check.net.NetChecked;
import com.tcs.model.ipdata.IpDataBean;
import com.tcs.server.ipdata.IpDataService;
import com.tcs.server.ipdata.impl.IpDataServiceImpl;
import com.tcs.util.constant.SystemConstants;
import com.tcs.util.spring.SpringConfigTool;

/**
* @Title: TimingValidationTask.java
* @Package com.tcs.validation.task
* @author 神经刀
* @date 2018年8月11日
* @version V1.0
 */
public class TimingValidationTask implements ITimingValidationTask , Runnable {
	
	private final Logger logger = LoggerFactory.getLogger(TimingValidationTask.class);
	
	private ICommonCacheTemplate iCommonCacheTemplate;
	
	private IpDataService ipDataService;
	
	private INetChecked iNetCacheked;
	
	public TimingValidationTask() {
		iCommonCacheTemplate = SpringConfigTool.getBean(RedisCacheTemplate.class);
		ipDataService = SpringConfigTool.getBean(IpDataServiceImpl.class);
		iNetCacheked = SpringConfigTool.getBean(NetChecked.class);
	}
	
	@Override
	public void validation() {
		// TODO Redis 分布式锁  对于并发不高.先判断key是否存在,然后在加锁.解锁. 参考 redisLock. 如果有问题,用 JedisCluster set(final String key, final String value, final String nxxx, final String expx, final long time) 这个方法即可.
		// 没解决原因: 此方案完全够用.不需要在改进. 后期做爬取海量数据时,上百个进程.可能要动此代码.
		logger.debug("正在试图获取锁");
		if (!iCommonCacheTemplate.exists(SystemConstants.ProxyPool.LOCK)) {
			// 考虑到单库,如果发生行锁,表锁.发生的暂时性堵塞.给了相应分钟的缓冲时间.
			try {
				iCommonCacheTemplate.setex(SystemConstants.ProxyPool.LOCK, 2 * 60, TimeUnit.SECONDS, "1");
				logger.debug(" 上锁成功!");
			} catch (Exception e) {
				logger.error("设置分布式锁失败,退出!" , e);
				try {
					this.wait(10 * 1000L);
				} catch (InterruptedException e1) {
					logger.error("此线程退出!" , e1);
					return;
				}
			}
			Integer count = ipDataService.count();
			IpDataBean ipDataBean = new IpDataBean();
			if (count > 1000) {
				ipDataBean.setPageSize(100);
				count = (count / ipDataBean.getPageSize()) + 1;
				for (int pageNum = 1; pageNum < count; pageNum++) {
					ipDataBean.setPageNum(pageNum);
					processData(ipDataBean);
				}
				try {
					Thread.sleep(5 * 1000L);
				} catch (InterruptedException e) {
					logger.error("此线程退出!" , e);
				}
			} else {
				processData(ipDataBean);
			}
			// 解锁
			iCommonCacheTemplate.del(SystemConstants.ProxyPool.LOCK);
			logger.debug("Thread exit redis lock!");
		}
		// Thread end!
	}
	
	private void processData(IpDataBean ipDataBean) {
		List<IpDataBean> ipDataRestultList = ipDataService.queyListByParams(ipDataBean);
		for (IpDataBean dataBean : ipDataRestultList) {
			if (!iNetCacheked.checkThrough(dataBean)) {
				logger.debug("dataBean : {}" , dataBean);
				ipDataService.deleteByParams(dataBean);
			}
		}
	}
	
	@Override
	public void run() {
		this.validation();
	}
}